package p2p.command;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.NoRouteToHostException;
import java.net.UnknownHostException;

import p2p.client.message.Message;
import p2p.peer.Peer;
import p2p.peer.PeerListener;
import p2p.peer.client.Client;
import p2p.util.Config;

public abstract class Command implements Runnable {

	protected String ip;
	protected PeerListener listener;
	protected Message message;
	protected int port;

	// Leave
	public Command(String ip, int port) {

		this.ip = ip;
		this.port = port;		
		this.message = new Message(2);
		this.message.setCommandObject(this);
		this.listener = Peer.getInstance().getListener();
		
	}

	// Spawn oder Connect
	public Command(int command, String ip, int port) {
		this.ip = ip;
		this.message = new Message(command, ip, port);
		this.message.setCommandObject(this);
		this.listener = Peer.getInstance().getListener();
		this.port = port;
	}
	
	// Spawn oder Connect
	public Command(int command, String ip) {
		this.ip = ip;
		//this.message = new Message(command, Integer.valueOf(ip));
		this.listener = Peer.getInstance().getListener();
	}

	public void waitForAck() {

		try {

			Thread.sleep(10000);

		} catch (InterruptedException e) {
			e.printStackTrace();
		}

	}

	public boolean isAcknowledged(Message m) {

		if (Peer.getInstance().isAcknowledged(m)) {

			this.listener.logPeerAction("Message UUID " + m.getUuid().toString() + " ack");
			return true;

		} else {

			this.listener.logPeerAction("Message UUID " + m.getUuid().toString() + " not ack");
			return false;

		}
	}

	@Override
	public void run() {

		Peer.getInstance().addAckMessage(this.message);

		DatagramSocket socket;

		try {

			while (!this.isAcknowledged(this.message)) {

				socket = new DatagramSocket();

				DatagramPacket request = new DatagramPacket(this.message.getTotalPayload(),
													this.message.getTotalPayload().length, 
													InetAddress.getByName(ip),
													this.message.getPort());

				socket.send(request);

				this.listener.logPeerAction("Command: " + this.message.getCommand()
						+ " Message UUID " + this.message.getUuid().toString()
						+ " is wating for ack");

				this.waitForAck();

			}

		} catch (NoRouteToHostException e) {

			this.listener.logPeerAction("No Route to host");

		} catch (UnknownHostException e) {

			this.listener.logPeerAction("No such host");

		} catch (Exception e) {

			e.printStackTrace();

		}

	}

	public abstract void execute();

}
